﻿using SanXiao.Game.Common;
using SanXiao.Game.GameCenter.SpecialEffects;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace SanXiao.Game.GameCenter.Block
{
    public unsafe abstract class BlockObject : GameObject
    {
        private readonly ImageObject _block;
        private SpecialEffectsObject _special;
        public BlockObject(GameType blockType, Size size, ImageObject block)
            : base(blockType, size)
        {
            _block = block;
        }
        public ImageObject Block => _block;
        public SpecialEffectsObject Special => _special;
        public event Action<int>? ScoreCallback;
        public override unsafe void Logic(GameObject* set)
        {
            if (!_isMD) return;
            _isMD = false;

            List<GameObject> list = new List<GameObject>(20);
            list.Add(this);

            CheckHorizontal(set, list, this);
            CheckVertical(set, list, this);

            if (list.Count < 3) return;

            ScoreCallback?.Invoke(list.Count << 1);

            foreach (var item in list)
            {
                BlockObject? block =item as BlockObject;

                if (block?.Special != null)
                {
                    block.HasEliminate = true;
                    block.Special.StartX = block.StartX;
                    block.Special.StartY = block.StartY;
                    block.Special.CellWidth = block.CellWidth;
                    block.Special.CellHeight = block.CellHeight;
                    block.Special.ZoomX = block.ZoomX;
                    block.Special.ZoomY = block.ZoomY;
                    block.Special.Row = block.Row;
                    block.Special.Column = block.Column;
                    block.Special.MaxColumn = block.MaxColumn;
                    block.Special.MaxRow = block.MaxRow;
                    block.Special.UpdateState();
                }
                //* (set + item.Row * MaxColumn + item.Column) = null;
            }
        }
        bool _isMD = false;
        public override void MouseDown(GameObject* set)
        {
            _isMD = true;
        }
        private void CheckVertical(GameObject* set, List<GameObject> list, GameObject gameObject)
        {
            CheckVerticalTop(set, list, gameObject);
            CheckVerticalBottom(set, list, gameObject);
        }
        private void CheckHorizontal(GameObject* set, List<GameObject> list, GameObject gameObject)
        {
            CheckHorizontalLeft(set, list, gameObject);
            CheckHorizontalRight(set, list, gameObject);
        }
        private void CheckVerticalTop(GameObject* set, List<GameObject> list, GameObject gameObject)
        {
            int row = gameObject.Row - 1;
            if (list.Any(t => t.Row == row && t.Column == gameObject.Column)) return;
            if (row >= 0)
            {
                GameObject* ptr = set + row * MaxColumn + gameObject.Column;
                if (*ptr != null && ptr->GameType == gameObject.GameType)
                {
                    list.Add(*ptr);
                    CheckVerticalTop(set, list, *ptr);
                    CheckHorizontal(set, list, *ptr);
                }
            }
        }
        private void CheckVerticalBottom(GameObject* set, List<GameObject> list, GameObject gameObject)
        {
            int row = gameObject.Row + 1;
            if (list.Any(t => t.Row == row && t.Column == gameObject.Column)) return;
            if (row < MaxRow)
            {
                GameObject* ptr = set + row * MaxColumn + gameObject.Column;
                if (*ptr != null && ptr->GameType == gameObject.GameType)
                {
                    list.Add(*ptr);
                    CheckVerticalBottom(set, list, *ptr);
                    CheckHorizontal(set, list, *ptr);
                }
            }
        }
        private void CheckHorizontalRight(GameObject* set, List<GameObject> list, GameObject gameObject)
        {
            int col = gameObject.Column + 1;
            if (list.Any(t => t.Row == gameObject.Row && t.Column == col)) return;
            if (col < MaxColumn)
            {
                GameObject* ptr = set + gameObject.Row * MaxColumn + col;
                if (*ptr != null && ptr->GameType == gameObject.GameType)
                {
                    list.Add(*ptr);
                    CheckHorizontalRight(set, list, *ptr);
                    CheckVertical(set, list, *ptr);
                }
            }
        }
        private void CheckHorizontalLeft(GameObject* set, List<GameObject> list, GameObject gameObject)
        {
            int col = gameObject.Column - 1;
            if (list.Any(t => t.Row == gameObject.Row && t.Column == col)) return;
            if (col >= 0)
            {
                GameObject* ptr = set + gameObject.Row * MaxColumn + col;
                if (*ptr != null && ptr->GameType == gameObject.GameType)
                {
                    list.Add(*ptr);
                    CheckHorizontalLeft(set, list, *ptr);
                    CheckVertical(set, list, *ptr);
                }
            }
        }
        public void SetSpecialEffects(SpecialEffectsObject special)
        {
            _special = special;
        }
        public override void Draw(Graphics g)
        {
            if(HasEliminate)
            {
                if(_special != null)
                    _special.Draw(g);
            }
            else
            {
                IntPtr hdc = g.GetHdc();
                DrawBlock(hdc);
                g.ReleaseHdc(hdc);
            }
        }
        private bool HasEliminate{ get; set; }
        private void DrawBlock(nint hdc)
        {
            GDI32.DrawImageTransparenc(hdc, _block.BitmapPtr, Location.X, Location.Y, _block.Width, _block.Height, Size.Width, Size.Height);
        }

        protected override void DisposeImage()
        {
            base.DisposeImage();
            _block?.Dispose();
        }
    }
}
